/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools io
 */

#include "io.h"

#include <memory>
#include <cinttypes>
#include <cmath>
#include <string>
#include <sys/types.h>
#include <fstream>

#include "hmfs_utils.h"
#include "hmfs_log.h"
#include "securec.h"

namespace OHOS {
namespace Hmfs {

int DevRead(FsData &fsInfo, void *buf, uint64_t offset, uint64_t len)
{
    if (fsInfo.deviceList.size() == 0) {
        return DevReadDevice(fsInfo.path, buf, offset, len);
    }

    DevInfo *devInfo = GetDeviceFd(fsInfo, offset);
    if (devInfo == nullptr) {
        HMFS_ERROR("Failed to find device, offset = %" PRIu64 ", blkId = %" PRIu64 ".",
            offset, offset / HMFS_BLOCK_SIZE);
        return -1;
    }

    return DevReadDevice(devInfo->path, buf, offset, len);
}

DevInfo* GetDeviceFd(FsData &fsInfo, uint64_t &offset)
{
    uint64_t blkId = offset / HMFS_BLOCK_SIZE;
    for (uint32_t i = 0; i < fsInfo.deviceList.size(); i++) {
        DevInfo& deviceInfo = fsInfo.deviceList[i];
        if ((deviceInfo.startBlkId <= blkId) && (deviceInfo.endBlkId >= blkId)) {
            offset -= deviceInfo.startBlkId * HMFS_BLOCK_SIZE;
            return &deviceInfo;
        }
    }
    return nullptr;
}

int DevReadDevice(std::string &path, void *buf, uint64_t offset, uint64_t len)
{
    std::ifstream file(path.c_str(), std::ios::in);
    if (!file) {
        HMFS_ERROR("Failed to open file, errno %d", errno);
        return -1;
    }

    file.seekg(offset);
    if (!file) {
        HMFS_ERROR("Failed to seekg, offset = %" PRIu64 ".", offset);
        return -1;
    }

    file.read((char*)buf, len);
    if (!file) {
        HMFS_ERROR("Failed to read buf, errno %d, offset = 0x%" PRIx64 ", blkId = %" PRIu64 ", len = 0x%" PRIx64 ".",
            errno, offset, offset / HMFS_BLOCK_SIZE, len);
        return -1;
    }

    return 0;
}
} // namespace Hmfs
} // namespace OHOS
